package com.tangruojie.service.impl;

import com.alibaba.fastjson2.annotation.JSONField;
import com.tangruojie.domain.po.User;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;

@Data
@NoArgsConstructor
public class UserDetailsImpl implements UserDetails {

    private User user;

    /**
     * 权限列表
     */
    private List<String> permissions;

    /**
     * 角色列表
     */
    private List<String> roles;

    @JSONField(serialize = false)
    private List<SimpleGrantedAuthority> authorities;

    public UserDetailsImpl(User user, List<String> permissions, List<String> roles) {
        this.user = user;
        this.permissions = permissions;
        this.roles = roles;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        if (authorities != null) {
            return authorities;
        }
        authorities = Stream.concat(
                        permissions.stream().filter(StringUtils::hasText).map(String::trim),
                        roles.stream().filter(StringUtils::hasText).map(role -> "ROLE_" + role.trim())
                )
                .distinct()
                .map(SimpleGrantedAuthority::new)
                .toList();
        return authorities;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUserName();
    }

}
/**
 * 1. 角色（Role）——粗粒度、身份/岗位定位
 * 例子：admin、user、editor、teacher、student
 * 用来做大范围入口控制：比如 /admin/** 只能管理员访问。
 * 角色常常和岗位/组织身份对应，一个用户可以有多个角色。
 * 2. 权限（Permission）——细粒度、操作/资源级
 * 例子：sys:user:list、sys:user:add、cms:post:publish
 * 用来做具体接口或按钮控制：比如普通用户有“查看”权限，但没有“删除”权限。
 * 权限粒度更细，可以随着功能点增加灵活扩展。
 * 3. 为什么要“角色 + 权限”一起用？
 * 只用角色：不灵活。你必须为每种操作建一个角色（爆炸式增长）。
 * 只用权限：不直观。用户无法简单地通过“我是管理员”快速获得一组权限。
 * 两者结合：
 * 角色作为权限的集合，便于运维分配；
 * 权限作为精细控制点，便于开发扩展。
 * 比如：
 * 角色 admin → 拥有 sys:user:* 全部权限
 * 角色 user → 拥有 sys:user:query、sys:user:update 部分权限
 * 当新增接口 sys:user:export，只需要赋给某些角色，不用动用户。
 */